import React, { useState } from 'react'
import NavBar from '@/components/NavBar'
import Input from '@/components/Input'
import classNames from 'classnames'
// 导入验证模块
import * as Yup from 'yup'
// 导入当前组件的样式
import styles from './index.module.scss'
// 使用formik来收集并绑定表单数据
import { useFormik } from 'formik'
import { useDispatch } from 'react-redux'
import { loginAsync } from '@/store/actions/login'
import { useLocation, useNavigate } from 'react-router-dom'
import { success } from '@/utils/tools'
import { sendCodeApi } from '@/api/login'
import type { Action, LoginData } from '@/types/login'
export default function Login() {
  const dispatch = useDispatch()
  const navigate = useNavigate()
  const location = useLocation()
  // Formik 表单对象
  const {
    isValid,
    errors,
    values,
    touched,
    handleBlur,
    handleChange,
    handleSubmit,
    setTouched,
  } = useFormik({
    // 设置表单字段的初始值
    initialValues: {
      mobile: '13911111112',
      code: '246810',
    },
    // 当表单提交的时候，会触发
    onSubmit: async (values: LoginData) => {
      // 接收到表单数据进行登录
      // console.log(values)
      await dispatch(loginAsync(values) as unknown as Action)
      success('登录成功', () => {
        // 登录成功后的回跳地址，根据回跳到登录前有没有记录地址来决定
        navigate(location.state || '/')
      })
    },
    // 使用Yup实现数据验证
    validationSchema: Yup.object().shape({
      // 手机号验证规则
      mobile: Yup.string()
        .required('请输入手机号')
        .matches(/^1[3-9]\d{9}$/, '手机号格式错误'),

      // 手机验证码验证规则
      code: Yup.string()
        .required('请输入验证码')
        .matches(/^\d{6}$/, '验证码6个数字'),
    }),
  })

  // 发送短信验证码
  // 定义短信倒计时初始数据
  const [time, setTime] = useState(0)
  const sendCode = async () => {
    // 如果当前的倒计时还没有完成，就不要发送短信验证码
    if (time > 0) return
    const { mobile } = values
    // 数据验证:必须是合法的手机号码格式
    if (!/^1[3-9]\d{9}$/.test(mobile)) {
      // 主体设置当前激活了表单的mobile选项，让错误信息跟表单校验时一样显示
      setTouched({
        mobile: true,
      })
      return
    }
    // 发送短信验证码
    try {
      await sendCodeApi(mobile)
      success('发送验证码成功', () => {
        // 开始进行短信倒计时
        // 设置倒计时的初始值
        setTime(5)
        let timeId = setInterval(() => {
          // setTime(time - 1) 这样修改数据是异步的，并不能立马拿到最新修改的值，还是上次的值
          // 当我们每次都想要获取到最新的状态，需要写成 箭头函数的形式
          setTime((time) => {
            if (time === 1) {
              clearInterval(timeId)
            }
            return time - 1
          })
        }, 1000)
      })
    } catch (err) {
      // todo
    }
  }

  return (
    <div className={styles.root}>
      <NavBar className="iconfanhui">登录</NavBar>
      <div className="content">
        {/* 标题 */}
        <h3>短信登录</h3>
        <form onSubmit={handleSubmit}>
          {/* 手机号输入框 */}
          <div className="input-item">
            <Input
              className="input-box"
              name="mobile"
              placeholder="请输入手机号"
              autoComplete="off"
              value={values.mobile}
              onChange={handleChange}
              onBlur={handleBlur}
            ></Input>
            {/* 收集错误信息 */}
            {touched.mobile && errors.mobile ? (
              <div className="validate">{errors.mobile}</div>
            ) : null}
          </div>

          {/* 短信验证码输入框 */}
          <div className="input-item">
            <Input
              className="input-box"
              name="code"
              placeholder="请输入验证码"
              maxLength={6}
              autoComplete="off"
              extra={time ? `${time}s后获取` : '获取验证码'}
              value={values.code}
              onChange={handleChange}
              onBlur={handleBlur}
              onExtraClick={sendCode}
            ></Input>
            {/* 收集错误信息 */}
            {touched.code && errors.code ? (
              <div className="validate">{errors.code}</div>
            ) : null}
          </div>

          {/* 登录按钮 */}
          <button
            type="submit"
            className={classNames('login-btn', { disabled: !isValid })}
            disabled={!isValid}
          >
            登录
          </button>
        </form>
      </div>
    </div>
  )
}
